#include <DigitalTube.h>

uint8_t DigitalTube::get_seg7(char ch) {
    static const uint8_t index_to_seg7[] = {
        /* 0-9 */ 
        0x3F, 0x06, 0x5B, 0x4F, 0x66,  // 0-4
        0x6D, 0x7D, 0x07, 0x7F, 0x6F,  // 5-9
        /* 符号 */
        0x80,   // 10: . 
        0x00,    // 11: (空格/非法字符)
    };

    auto char_to_index = [](char ch) -> uint8_t {
        if (ch >= '0' && ch <= '9') return ch - '0';
        switch(ch) {
            case '.': return 10;
            case ' ': return 11;
            default: return 11;
        }
    };

    return index_to_seg7[char_to_index(ch)];

}

DigitalTube::DigitalTube(const uint8_t (&pos_pins)[8], const uint8_t (&neg_pins)[3]) {
    for (uint8_t i = 0; i < 8; ++i) {
        this->pos_pins[i] = pos_pins[i];
        if (i < 4) {
            this->neg_pins[i] = neg_pins[i];
        }
    }
}


void DigitalTube::begin() {
    for (uint8_t i = 0; i < 8; ++i) {
        pinMode(this->pos_pins[i], OUTPUT);
        digitalWrite(this->pos_pins[i], LOW);
        if (i < 4) {
            pinMode(this->neg_pins[i], OUTPUT);
            digitalWrite(this->neg_pins[i], LOW);
        }
    }    
};

/**
 * \brief 点亮某一行中的led
 *
 * \param row 点亮某一行，如果输入1则点亮第一行
 * \param which_leds 点亮哪些LED，如果输入0x88（1000 1000），则点亮第一个和第五个LED
 */
bool DigitalTube::lit(uint8_t index, char ch)  {
    if (index < 1 || index > 8) {
        return false;
    }
    
    // row-1的二进制位对应三个引脚的状态
    uint8_t row_code = index - 1;
    digitalWrite(neg_pins[0], (row_code & 0x01) ? HIGH : LOW);
    digitalWrite(neg_pins[1], (row_code & 0x02) ? HIGH : LOW);
    digitalWrite(neg_pins[2], (row_code & 0x04) ? HIGH : LOW);

    uint8_t seg7 = get_seg7(ch);


    for (uint8_t i = 0; i < 8; ++i) {
        digitalWrite(pos_pins[i], (seg7 >> i) & 0x01);
    }

    return true;
}